---@class RedRob.Player:RedRob.Pawn
---@field New fun():RedRob.Player
---@field ai RedRob.PlayerAi
local Player = RedRob.CreateClass("Player","Pawn")

local DEBUFF_PATH = "Prefabs/Skill/b025"

---@param eventData Spine.EventData
local function AnimationEvent(event , eventData)

    if not eventData then return end
    local skillId = eventData.Int
    local casterId = eventData.String
    local caster = RedRob.ActorManager.GetActor(casterId)
    RedRob.ReportMgr.Print("AnimationEvent casterId:skillId:",casterId,skillId)
    if caster and not caster:IsDead() then
        local skill = caster.skillMgr:GetSkill(skillId)
        if not skill then return end
        skill:Hit()
    end
end


function Player:OnCreate()
    self.clientId = 0
    self.clientName = ""
    self.isLoading = false
    self.isLoaded = false
    self.height = 1 --身高
    self.skinId = 0
    self.modelId = 1
    self.picFrame = 0
    self.modelName = ""
    self.modelObj = nil
    self.LoadRequestId = 0
    ---@type Spine.Unity.SkeletonAnimation
    self.animation = nil
    self.attackRadius = 1.1
    self.speed = 4
    self.targetId = 0
    self.isInBattle = false
    self.unionName = ""         --公会名
    ---@type UnityEngine.Renderer[]
    self.renders = nil
    self.stateCtrl = RedRob.StateController.New()
    self.stateCtrl:OnCreate(self)
    self:EnterState(RedRob.Config.ActionState.idle)
    self.hp = 100
    self.hpMax = 100
    self.lockHp = 0
    ---@type Spine.Bone[] 骨骼节点
    self.bones = {}
    ---@type Spine.EventData
    self.animEventData = Spine.EventData.New("");
    self:SetAttr(EnumConst.FighterAttributeEnum.SPEED ,self.speed)
    self.winDebuffEffect = nil
    local scale = RedRob.ClientBattle.PLAYER_SCALE
    Util.Lua_SetLocalScaleXYZ(self.transform,scale,scale,scale)
end

function Player:OnDestroy()
    self.isLoadRes = false
    self.LoadRequestId = 0
    RedRob.EffectMgr.DestroyEffectByCaster(self:GetId())
    RedRob.BufferMgr.RemoveBuff(self:GetId())
    RedRob.PoolMgr.CancelLoad(self.LoadRequestId)
    RedRob.PoolMgr.ReturnPrefabToPool(self.modelName,self.modelObj)
    if self.animation then
        -- self.animation.state.UserEvent = self.animation.state.UserEvent - AnimationEvent
        self.animation:UnRegisterStateLuaUserFunction()
    end
    --[[if self.modelObj then
        destroy(self.modelObj)
    end]]
    self.modelName = ""
    self.modelObj = nil
    self.animation = nil
    if self.stateCtrl then
        self.stateCtrl:OnDestroy()
    end
    if self.skillMgr then
        self.skillMgr:OnDestroy()
    end
    self.skillMgr = nil
    self.isInBattle = false
    self.stateCtrl = nil
    self.renders = nil
    self.winDebuffEffect = nil
end
function Player:EquipSkill()
    self.skillMgr = RedRob.SkillMgr.New()
    self.skillMgr:OnCreate(self)
end
function Player:LoadModel()
    if self.isLoading then
        return
    end
    local name = logicMgr.SkinManager.GetHeroModelPathBySkinId(self.skinId, self.modelId)
    if self.modelName == name then
        return
    end
    self.modelName = name
    self.isLoading = true
    self.LoadRequestId = RedRob.PoolMgr.LoadPrefabFromPool(self.modelName,self.LoadCallback,self)
end
function Player:LoadCallback(go)
    if self.isDestroyed then
        return
    end
    self.isLoaded = true
    self.modelObj = go--newObject(go)
    self.modelObj.transform:SetParent(self.transform,false)
    self.animation = self.modelObj:GetComponentInChildren(TSkeletonAnimation)
    self.renders = self.gameObject:GetComponentsInChildren(typeof(UnityEngine.Renderer))
    self:InitObject()

    EquipManager.setWeaponSkin(self.animation.gameObject,self.modelId,false,0)
    local state = self:GetActionState()
    if state then
        self:EnterState(state.stateId,state.data)
    end
    --local rebornEff = RedRob.EffectMgr.CreateEffect(self.id,"Prefabs/Skill/fxh104","idle2",self.pos.x,self.pos.y,nil,self:GetSortingOrder())
    --rebornEff:RegisterOrderChanged(self)
end
---@private
function Player:InitObject()

    self.gameObject.name = "p"..self.id
    Util.Lua_SetLocalPositionXYZ(self.transform,self.pos.x,self.pos.y,self.pos.z)
    Util.Lua_SetLocalRotationXYZ(self.animation.transform,0,0,0)
    self.boxCollider.size = Vector3(1.5,3,0.01)
    self.boxCollider.center = Vector3(0,1.5,0)
    self:SetDir(self.isLeft)
    for k,v in pairs(RedRob.Config.RoleBoneNames) do
        local bone = self.animation.Skeleton:FindBone(v)
        self.bones[v] = bone
    end
    -- self.animation.state.UserEvent = self.animation.state.UserEvent + AnimationEvent
    self.animation:RegisterStateLuaUserFunction(AnimationEvent)
    FireEvent(RedRob.Config.Event.ActorPosChanged,self)
end
function Player:GetAnimation()
    return self.animation
end
function Player:GetSpeed()
    return self.speed
end

function Player:GetModelId()
    return self.modelId
end
function Player:GetPicFrame()
    return self.picFrame
end
function Player:GetBonePos(name,onlyBonePos)
    local bone = self.bones[name]
    if not bone then return 0,0 end
    if onlyBonePos then
        return bone.WorldX,bone.WorldY
    else
        return self.pos.x + bone.WorldX,self.pos.y + bone.WorldY
    end
end
function Player:GetActionState()
    return self.stateCtrl.curActionState
end
function Player:GetActionStateId()
    if self.stateCtrl.curActionState then
        return self.stateCtrl.curActionState.stateId
    end
    return RedRob.Config.ActionState.idle
end
function Player:GetClientName()
    return self.clientName
end
function Player:IsLoaded()
    return self.isLoaded
end
function Player:GetAttackRadius()
    return self.attackRadius
end
function Player:IsInBattle()
    return self.isInBattle
end
function Player:SetInBattle(inBattle)
    local old = self.isInBattle
    self.isInBattle = inBattle
    if old ~= inBattle then
        FireEvent(RedRob.Config.Event.PlayerInBattle,self)
    end
    self:Print("Player:SetInBattle",inBattle)
end
function Player:IsReady()
    return self.isReady
end
function Player:SetReady(isReady)
    self:Print("Player:SetReady",isReady)
    self.isReady = isReady
end
function Player:SetAnimEventData(skillId)
    if self.isSetEventData then
        return
    end
    self.isSetEventData = true
    self.animEventData.Int = skillId;
    self.animEventData.String = self.id;
    self.animation.state.UserData = self.animEventData
end
---@param target RedRob.Player
function Player:FightPlayer(target, isWin, timeStamp, totalTime, x, y)
    if not target then
        return
    end
    if self.targetId ~= 0 then
        self:Print("target:isAlready have ","old:"..self.targetId,"new:"..target:GetId())
        logError("target:isAlready have","old:"..self.targetId,"new:"..target:GetId())
    end
    self:Print("Player:GotoFight isWin/id",isWin,target:GetId())
    self.ai:FightPlayer(target,isWin,timeStamp,totalTime,x,y)
end
function Player:Fight(target,damage)
    self.ai:Fight(target,damage)
end
--是否可攻击
function Player:CanAttack()
    if self.isInBattle or self.isDead or self:IsUnSelectState() then
        return false
    end
    return true
end
function Player:Attack()
    self:DoSkill(RedRob.Config.SkillShowType.normalAttack)
end
function Player:CancelAttack(inIdle)
    self.ai:CancelAttack(inIdle)
    self:EndAllSkill()
end
function Player:SetAttackValue(value)
    local skill = self.skillMgr:GetEquippedSkill(RedRob.Config.SkillShowType.normalAttack)
    if skill then
        skill:SetDamageValue(value)
    end
end
function Player:GetSkillDuring(skillType)
    local skill = self.skillMgr:GetEquippedSkill(skillType)
    if not skill then return 0 end
    return skill.maxCd
end

function Player:EndAllSkill()
    self.skillMgr:EndAllSkill()
end
function Player:DoSkill(skillType)
    if self.isDead then
        return
    end
    local s = self.skillMgr:GetEquippedSkill(skillType)
    if s and not s:IsInCD() then
        self.isSetEventData = false
    end
    self.skillMgr:DoEquippedSkill(skillType)
end
function Player:EnterState(stateId,data)
    self:Print("Player:EnterState",stateId)
    self.stateCtrl:EnterState(stateId,data)
end
---@param actor RedRob.Actor
function Player:SetTarget(actor)
    if actor then
        self.targetId = actor:GetId()
    else
        self.targetId = 0
    end
end
function Player:HasTarget()
    return self.targetId ~= 0
end
function Player:IsInIdle()
    if self:GetActionStateId() == RedRob.Config.ActionState.idle then
        return true
    end
    return false
end
---@return RedRob.Player
function Player:GetTarget()
    return RedRob.ActorManager.GetActor(self.targetId)
end
function Player:GetAnimStateDuring(name)
    if self.animation then
        local anim = self.animation.skeleton.Data:FindAnimation(name)
        if anim then
            return anim.Duration
        end
    end
    return 1.5
end
function Player:StartReborn(time)
    self:ShowObject(false)
    self:Print("StartReborn ",self:GetId())
    FireEvent(RedRob.Config.Event.PlayerStartReborn,self,time)
end
--重生
function Player:Reborn(x,y)
    --print(RedRob.ClientBattle.GetBattleTime())
    self:Print("Reborn ",self:GetId())
    self.isDead = false
    self:SetTarget(nil)
    self:SetHp(self.hpMax)
    self:CancelAttack()
    self:ShowObject(true)
    self:SetInBattle(false)
    self:SetPos(x,y)
    self:EnterState(RedRob.Config.ActionState.idle)
    FireEvent(RedRob.Config.Event.PlayerReborn,self)
    local rebornEff = RedRob.EffectMgr.CreateEffect(self.id,"Prefabs/Skill/fxh104","idle2",self.pos.x,self.pos.y,nil,self:GetSortingOrder())
    rebornEff:RegisterOrderChanged(self)
end
--胜利
function Player:Win()
    self.skillMgr:EndAllSkill(true)
    self:AddBuff(210001400,1,3)--提前加上不可选中buff
    self:LoadWinDebuff()
    --self:EnterState(RedRob.Config.ActionState.win,1)
    FireEvent(RedRob.Config.Event.PlayerWin,self)
end
--受到伤害
---@param attackPlayer RedRob.Player
function Player:Hurt(hp,attackPlayer,ignoreLock)
    if self.isDead then return end
    if ignoreLock then
        hp = math.max(0,self.hp - hp)
    else
        hp = math.max(self.lockHp,self.hp - hp)
    end
    self:SetHp(hp)
    if self.hp <= 0 then
        RedRob.GameMode.SetAttrReduce(self.id,0)
        self.skillMgr:EndAllSkill(true)
        --RedRob.EffectMgr.DestroyEffectByCaster(self.id)
        self:SetDead()
        self:LoadWinDebuff()
        self:EnterState(RedRob.Config.ActionState.failed)
        FireEvent(RedRob.Config.Event.ActorDead,self,attackPlayer)
    end
    FireEvent(RedRob.Config.Event.PlayerHpChanged,self,attackPlayer)
end
function Player:SetHp(hp)
    if hp <= 0 then
        hp = 0
    end
    self.hp = hp
end
function Player:LockHp(hp)
    self.lockHp = hp
end
function Player:SetHpMax(hpMax)
    self.hpMax = hpMax
end
function Player:GetHp()
    return self.hp
end
function Player:GetHpMax()
    return self.hpMax
end
--- 0~1
function Player:GetHpRate()
    return self.hp/self.hpMax
end
function Player:GetHeight()
    return self.height
end
---endDirection 0: right 朝向 ,1: left ,-1 or nil:不设置最终朝向
function Player:MoveToDestination(x,y,endDirection,callback)
    self.ai:MoveToDestinationByXYZ(x,y,endDirection,callback)
end
function Player:Update(dt)
    if not self.isActive then return end
    if self:GetTran() == nil then return end
    self.stateCtrl:Update(dt)
    self.ai:Update(dt)
    self.skillMgr:Update(dt)
end
function Player:SetSortingOrder(order)
    if self.sortingOrder == order then
        return
    end
    if not self.renders then return end
    if self:IsDead() then return end
    if not RedRob.CameraController.IsPlayerInScreen(self) then
        return
    end
    RedRob.Pawn.SetSortingOrder(self,order)
    local length = self.renders.Length
    for i = 0 , length - 1 do
        self.renders[i].sortingOrder = self:GetSortingOrder() + i
    end
end
--不可选中
function Player:IsUnSelectState()
    local _list = RedRob.BufferMgr.GetBuffList(self.id)
    if not _list then return false end
    for k,v in pairs(_list) do
        if v:HasUnSelectState() then
            return true
        end
    end
    return false
end
function Player:SetDir(isLeft)
    self:Print("SetDir",isLeft)
    RedRob.Pawn.SetDir(self,isLeft)
    if self.animation then
        Util.SetFlipX(self.animation, isLeft);
        if self.shadow then
            self.shadow:setFlip( isLeft);
        end
    end
end
function Player:AddBuff(buffId, overlay,during)
    RedRob.Pawn.AddBuff(self,buffId,overlay,during)
    self:CalcAttr()
end
function Player:CalcAttr()
    table.clear(self.attrList)
    --这里只处理移速，其他服务器处理
    local buffList = RedRob.BufferMgr.GetBuffList(self.id)
    for k,v in pairs(buffList) do
        local cfg = dataTable.getDataTableByStringId("t_buff",v.buffId)
        if cfg and not string.IsNilOrEmpty(cfg.f_Atribute) then
            local attrs = decodeJsonStrToTabel(cfg.f_Atribute)
            for k2,v2 in pairs(attrs) do
                local attrId = tonumber(v2[1])
                local value = tonumber(v2[2])
                self:SetAttr(attrId,self:GetAttr(attrId) + value * v.overlay)
            end
        end
    end
    self:SetAttr(EnumConst.FighterAttributeEnum.SPEED,(self:GetAttr(EnumConst.FighterAttributeEnum.SPEED_PER)/10000+1) * self.speed)
end

function Player:LoadWinDebuff()
    local data = RedRob.GameMode.GetPlayerData(self:GetId())
    if data and data.buff ~= 0 then
        if self.winDebuffEffect then
            return
        end
        --self.winDebuffEffect = RedRob.EffectMgr.CreateSimpleEffect(self.clientId,"Prefabs/Skill/b025",0,0,self.sortingOrder,true)
        self.winDebuffEffect = RedRob.EffectMgr.CreateEffect(self:GetId(),DEBUFF_PATH,"",0,0,nil,self:GetSortingOrder(),self:GetId())
        self.winDebuffEffect:RegisterOrderChanged(self)
    else
        self:DestroyDebuff()
    end
end
function Player:DestroyDebuff()
    RedRob.EffectMgr.DestroyEffect(self.winDebuffEffect)
    self.winDebuffEffect = nil
end